package com.quark.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quark.common.jwt.JwtTokenManager;
import com.quark.mapper.system.SysUserInfoMapper;
import com.quark.mapper.system.SysUserMapper;
import com.quark.mapper.system.SysUserRoleMapper;
import com.quark.model.system.user.*;
import com.quark.model.system.user.vo.AuUserVO;
import com.quark.model.system.user.vo.UserPasswordVO;
import com.quark.common.exception.CustomException;
import com.quark.service.redis.RedisService;
import com.quark.util.SecurityUtils;
import com.quark.model.system.user.dto.UserDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author 张高昌
 * @date 2021/11/1 20:50
 * @description TODO
 */
@Service
@RequiredArgsConstructor
public class UserService {

    private final RedisService redisService;

    private final SysUserMapper sysUserMapper;

    private final JwtTokenManager jwtTokenManager;

    private final PasswordEncoder passwordEncoder;

    private final UserDetailsService userDetailsService;

    private final SysUserRoleMapper sysUserRoleMapper;

    private final SysUserInfoMapper sysUserInfoMapper;


    @Value("${jwt.tokenHead}")
    private String tokenHead;

    public Map<String, Object> doLogin(LoginModel loginModel, HttpServletRequest req) {
        String code = (String) req.getSession().getAttribute("code");
        if (!loginModel.getCode().equals(code)) {
            throw new CustomException("验证码错误！");
        }

        UserDetails userDetails = userDetailsService.loadUserByUsername(loginModel.getLoginame());
//        String password = loginModel.getPassword();
//        if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) {
//            throw new CustomException("用户名或密码错误！");
//        }

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,
                null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        String token = jwtTokenManager.generateToken(userDetails);
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);

        return tokenMap;
    }

    public Map getUserInfo(Principal principal) {
        SysUser sysUser = sysUserMapper.selectByUserName(principal.getName());
        Map<String, Object> objectMap = new HashMap<>();
        objectMap.put("name", principal.getName());
        objectMap.put("userInfo", sysUser);
        objectMap.put("avatar", "http://img.qqzhi.com/uploads/2018-11-30/023008692.jpg");
        objectMap.put("introduction", "I am a super administrator");
        return objectMap;
    }

    public IPage<UserDTO> getMenuPageList(Page page, UserPageVO model) {

        return sysUserMapper.selectPageVo(page, model);
    }

    public boolean addUser(AuUserVO vo) {
        AdminUser user = SecurityUtils.getUser();
        String password = passwordEncoder.encode(vo.getPassword());
        Long userId = user.getId();
        SysUser sysUser = new SysUser();
        sysUser.setUserName(vo.getUserName());
        sysUser.setPassword(password);
        sysUser.setState(1);
        sysUser.setCreateUser(userId);
        sysUser.setCreateTime(new Date());
        sysUserMapper.insertSelective(sysUser);
        SysUserInfo sysUserInfo = new SysUserInfo();
        sysUserInfo.setUId(sysUser.getId());
        sysUserInfo.setGender(vo.getGender());
        sysUserInfo.setPhone(vo.getPhone());
        sysUserInfo.setEmail(vo.getEmail());
        sysUserInfo.setCreateTime(LocalDateTime.now());
        sysUserInfoMapper.insertSelective(sysUserInfo);
        //添加角色
        return userRole(vo, sysUser.getId());
    }

    public boolean updateUser(AuUserVO vo) {
        SysUserInfo sysUserInfo = new SysUserInfo();
        sysUserInfo.setUId(vo.getId());
        sysUserInfo.setPhone(vo.getPhone());
        sysUserInfoMapper.updateByPrimaryKeySelective(sysUserInfo);
        //先删除在添加
        sysUserRoleMapper.deleteByUserId(vo.getId());
        //添加角色
        return userRole(vo, vo.getId());
    }

    private boolean userRole(AuUserVO vo, Long id) {
        Integer[] rid = vo.getRid();
        List<SysUserRole> listUserRole = new LinkedList<>();
        for (Integer integer : rid) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(id);
            sysUserRole.setRId(integer);
            listUserRole.add(sysUserRole);
        }
        sysUserRoleMapper.batchAdd(listUserRole);
        redisService.del("sys_user:" + id);
        redisService.del("sys_user_role:" + id);
        return true;
    }

    /**
     * 根据用户id删除用户
     *
     * @param id
     * @return
     */
    public boolean deleteUserById(long id) {
        int flag = sysUserMapper.deleteByPrimaryKey(id);
        return flag > 0;
    }

    /**
     * 修改用户状态
     *
     * @param id
     * @param status
     * @return
     */
    public boolean updateUserState(long id, int status) {
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setState(status);
        int i = sysUserMapper.updateByPrimaryKeySelective(sysUser);
        return i > 0;
    }

    /**
     * 修改用户密码
     *
     * @param vo
     * @return
     */
    public boolean updateUserPassword(UserPasswordVO vo) {
        SysUser sysUser = new SysUser();
        String password = passwordEncoder.encode(vo.getPassword());
        sysUser.setId(vo.getId());
        sysUser.setPassword(password);
        int flag = sysUserMapper.updateByPrimaryKeySelective(sysUser);

        return flag > 0;
    }
}
